package org.codehaus.activemq.management;

import java.util.List;
import javax.management.j2ee.statistics.CountStatistic;
import javax.management.j2ee.statistics.JMSConsumerStats;
import javax.management.j2ee.statistics.JMSProducerStats;
import javax.management.j2ee.statistics.JMSSessionStats;
import javax.management.j2ee.statistics.TimeStatistic;
import org.codehaus.activemq.ActiveMQMessageConsumer;
import org.codehaus.activemq.ActiveMQMessageProducer;
import org.codehaus.activemq.util.IndentPrinter;

public class JMSSessionStatsImpl extends StatsImpl
  implements JMSSessionStats
{
  private List producers;
  private List consumers;
  private CountStatistic messageCount;
  private CountStatistic pendingMessageCount;
  private CountStatistic expiredMessageCount;
  private TimeStatistic messageWaitTime;
  private CountStatisticImpl durableSubscriptionCount;
  private TimeStatisticImpl messageRateTime;

  public JMSSessionStatsImpl(List producers, List consumers)
  {
    this.producers = producers;
    this.consumers = consumers;
    this.messageCount = new CountStatisticImpl("messageCount", "Number of messages exchanged");
    this.pendingMessageCount = new CountStatisticImpl("pendingMessageCount", "Number of pending messages");
    this.expiredMessageCount = new CountStatisticImpl("expiredMessageCount", "Number of expired messages");
    this.messageWaitTime = new TimeStatisticImpl("messageWaitTime", "Time spent by a message before being delivered");
    this.durableSubscriptionCount = new CountStatisticImpl("durableSubscriptionCount", "The number of durable subscriptions");
    this.messageWaitTime = new TimeStatisticImpl("messageWaitTime", "Time spent by a message before being delivered");
    this.messageRateTime = new TimeStatisticImpl("messageRateTime", "Time taken to process a message (thoughtput rate)");

    addStatistic("messageCount", this.messageCount);
    addStatistic("pendingMessageCount", this.pendingMessageCount);
    addStatistic("expiredMessageCount", this.expiredMessageCount);
    addStatistic("messageWaitTime", this.messageWaitTime);
    addStatistic("durableSubscriptionCount", this.durableSubscriptionCount);
    addStatistic("messageRateTime", this.messageRateTime);
  }

  public JMSProducerStats[] getProducers()
  {
    Object[] producerArray = this.producers.toArray();
    int size = producerArray.length;
    JMSProducerStats[] answer = new JMSProducerStats[size];
    for (int i = 0; i < size; i++) {
      ActiveMQMessageProducer producer = (ActiveMQMessageProducer)producerArray[i];
      answer[i] = producer.getProducerStats();
    }
    return answer;
  }

  public JMSConsumerStats[] getConsumers()
  {
    Object[] consumerArray = this.consumers.toArray();
    int size = consumerArray.length;
    JMSConsumerStats[] answer = new JMSConsumerStats[size];
    for (int i = 0; i < size; i++) {
      ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer)consumerArray[i];
      answer[i] = consumer.getConsumerStats();
    }
    return answer;
  }

  public CountStatistic getMessageCount() {
    return this.messageCount;
  }

  public CountStatistic getPendingMessageCount() {
    return this.pendingMessageCount;
  }

  public CountStatistic getExpiredMessageCount() {
    return this.expiredMessageCount;
  }

  public TimeStatistic getMessageWaitTime() {
    return this.messageWaitTime;
  }

  public CountStatistic getDurableSubscriptionCount() {
    return this.durableSubscriptionCount;
  }

  public TimeStatisticImpl getMessageRateTime() {
    return this.messageRateTime;
  }

  public String toString() {
    StringBuffer buffer = new StringBuffer(" ");
    buffer.append(this.messageCount);
    buffer.append(" ");
    buffer.append(this.messageRateTime);
    buffer.append(" ");
    buffer.append(this.pendingMessageCount);
    buffer.append(" ");
    buffer.append(this.expiredMessageCount);
    buffer.append(" ");
    buffer.append(this.messageWaitTime);
    buffer.append(" ");
    buffer.append(this.durableSubscriptionCount);

    buffer.append(" producers{ ");
    JMSProducerStats[] producerArray = getProducers();
    for (int i = 0; i < producerArray.length; i++) {
      if (i > 0) {
        buffer.append(", ");
      }
      buffer.append(Integer.toString(i));
      buffer.append(" = ");
      buffer.append(producerArray[i]);
    }
    buffer.append(" } consumers{ ");
    JMSConsumerStats[] consumerArray = getConsumers();
    for (int i = 0; i < consumerArray.length; i++) {
      if (i > 0) {
        buffer.append(", ");
      }
      buffer.append(Integer.toString(i));
      buffer.append(" = ");
      buffer.append(consumerArray[i]);
    }
    buffer.append(" }");
    return buffer.toString();
  }

  public void dump(IndentPrinter out) {
    out.printIndent();
    out.println(this.messageCount);
    out.printIndent();
    out.println(this.messageRateTime);
    out.printIndent();
    out.println(this.pendingMessageCount);
    out.printIndent();
    out.println(this.expiredMessageCount);
    out.printIndent();
    out.println(this.messageWaitTime);
    out.printIndent();
    out.println(this.durableSubscriptionCount);
    out.println();

    out.printIndent();
    out.println("producers {");
    out.incrementIndent();
    JMSProducerStats[] producerArray = getProducers();
    for (int i = 0; i < producerArray.length; i++) {
      JMSProducerStatsImpl producer = (JMSProducerStatsImpl)producerArray[i];
      producer.dump(out);
    }
    out.decrementIndent();
    out.printIndent();
    out.println("}");

    out.printIndent();
    out.println("consumers {");
    out.incrementIndent();
    JMSConsumerStats[] consumerArray = getConsumers();
    for (int i = 0; i < consumerArray.length; i++) {
      JMSConsumerStatsImpl consumer = (JMSConsumerStatsImpl)consumerArray[i];
      consumer.dump(out);
    }
    out.decrementIndent();
    out.printIndent();
    out.println("}");
  }

  public void onCreateDurableSubscriber() {
    this.durableSubscriptionCount.increment();
  }

  public void onRemoveDurableSubscriber() {
    this.durableSubscriptionCount.decrement();
  }
}